package com.spring.forum.utils;

import com.spring.forum.constants.Constants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

@Slf4j
public class JwtUtils {
    // 过期时间 1 分钟 (ms)
    private static final long JWT_EXPIRATION_TIME = 60 * 1000;

    // 生成密钥
    private static SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    // 上面方法生成之后我们拿不到密钥，所以使用该方法获得密钥
    private static String getSecret = Encoders.BASE64.encode(secretKey.getEncoded());

    /**
     * 生成token
     */
    public static String generateToken(Map<String, Object> claims) {
        String token = Jwts.builder()
                .setClaims(claims) // 负载部分存放的信息
                .setIssuedAt(new Date(System.currentTimeMillis())) // 设置签发时间
                .setExpiration(new Date(System.currentTimeMillis()+JWT_EXPIRATION_TIME)) // 设置过期时间
                .signWith(secretKey) // 签名算法，需要传一个密钥
                .compact(); // 将上述信息组合起来
        return token;
    }

    /**
     * 校验token
     */
    // 这里返回 Claims 类型，该类型继承Map
    // 后续可以方便我们从token中拿取一些数据
    // 返回null说明校验失败
    public static Claims parseToken(String token) {
        // 创建解析器，将密钥放进去
        JwtParser builder = Jwts.parserBuilder().setSigningKey(secretKey).build();
        Claims claims = null;
        try {
            claims = builder.parseClaimsJws(token).getBody();
        }catch (Exception e) {
            // 解析失败
            log.info("解析token失败:" + e.getMessage());
            e.printStackTrace();
            return null;
        }
        // 成功返回true
        return claims;
    }

    /**
     * 从token中获取用户id
     */
    public static Integer getUserIdByToken(String token) {
        // 解析 token
        Claims claims = parseToken(token);
        if (claims != null) {
            Integer userId = (Integer) claims.get(Constants.TOKEN_ID);
            if (userId > 0) {
                // 如果 userId 是合法的才返回
                return userId;
            }
        }
        // 解析失败或其他情况返回null
        return null;
    }
}
